import 'dart:io';

import 'package:deb_packer/src/yaml_handler.dart';
import 'package:path/path.dart' as p;

import 'src/cli_logger.dart';

import 'package:yaml/yaml.dart';

class DebPacker {
  late YamlHandler handler;
  final String _defaultBuildDist = '${p.current}/build/deb';

  Map<String, dynamic> _getConfig({String? configFile}) {
    String filePath;
    if (configFile != null) {
      if (File(configFile).existsSync()) {
        filePath = configFile;
      } else {
        CliLogger.error('The config file `$configFile` was not found.');
        exit(1);
      }
    } else if (File('deb_packer.yaml').existsSync()) {
      filePath = 'deb_packer.yaml';
    } else {
      filePath = 'pubspec.yaml';
    }

    final yamlMap = (loadYaml(File(filePath).readAsStringSync()) ?? {}) as Map;

    if (yamlMap['deb_packer'] is! Map) {
      CliLogger.error(
          "Your $filePath file does not contain a 'deb_packer' section.");
      exit(1);
    }

    // yamlMap has the type YamlMap, which has several unwanted side effects
    return _yamlToMap(yamlMap['deb_packer'] as YamlMap);
  }

  Map<String, dynamic> _handleConfig(Map<String, dynamic> yamlMap) {
    if (yamlMap['control'] == null) {
      CliLogger.error("Your config file does not contain a 'control' section.");
      exit(1);
    }

    handler = YamlHandler();
    handler.setDebConfig(yamlMap);
    return {};
  }

  Map<String, dynamic> _yamlToMap(YamlMap yamlMap) {
    final map = <String, dynamic>{};
    for (final entry in yamlMap.entries) {
      if (entry.value is YamlList) {
        final list = <String>[];
        for (final value in entry.value as YamlList) {
          if (value is String) {
            list.add(value);
          }
        }
        map[entry.key as String] = list;
      } else if (entry.value is YamlMap) {
        map[entry.key as String] = _yamlToMap(entry.value as YamlMap);
      } else {
        map[entry.key as String] = entry.value;
      }
    }
    return map;
  }

  void _buildDebian(String buildDist) async {
    handler.build(buildDist);
  }

  void createDebFolder({String? path, String? buildDist}) {
    var config = _getConfig(configFile: path);
    _handleConfig(config);
    _buildDebian(buildDist ?? _defaultBuildDist);
  }
}
